package com.xhwl.centiotdata.suppliersystem.leopen;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.utils.RedisUtils;
import com.xhwl.common.exception.ApplicationException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import static com.xhwl.centiotdata.pojo.constant.LeopenConstant.LENIU_API_AUTH;
import static com.xhwl.centiotdata.pojo.constant.LeopenConstant.LENIU_TOKEN_KEY;

/**
 * @author pengjunming
 * @description
 * @date 2023/2/11 14:41
 */
@Service
@Slf4j
public class GeneralLeopenHandler {

    @Resource
    private RedisUtils redisUtils;

    /**
     * 获取授权
     */
    private String onGettingToken(String appId, String appKey, String apiKey, String host) {

        String key = String.format(LENIU_TOKEN_KEY, appId);
        String token = (String) redisUtils.get(key);
        if (StringUtils.isNotBlank(token)) {
            return token;
        }
        Map<String, Object> params = onBuildsRequestBody(
                Dict.create().set("appId", appId).set("appSecret", appKey), apiKey
        );

        String response = HttpUtil.post(host + LENIU_API_AUTH, JSONUtil.toJsonStr(params));
        JSONObject json = JSON.parseObject(response);
        log.info("请求乐牛参数：{}，结果：{}", params, json.toJSONString());

        JSONObject data = json.getJSONObject("data");
        if (data != null && data.containsKey("accessToken")) {
            token = data.getString("accessToken");
            redisUtils.setWithMinute(key, token, 110);
        }
        return token;
    }

    /**
     * 提交请求
     */
    public JSONObject onPosting(String appId, String appKey, String apiKey, String host, String path, Object content) {
        String token = onGettingToken(appId, appKey, apiKey, host);
        if (StringUtils.isBlank(token)) {
            throw new ApplicationException("获取平台授权信息失败");
        }
        Map<String, Object> params = onBuildsRequestBody(content, apiKey);
        HttpRequest request = HttpUtil.createPost(host + path);
        request.header("Authorization", "Bearer " + token);
        request.body(JSONUtil.toJsonStr(params), ContentType.JSON.toString());
        String response = request.execute().body();
        JSONObject jsonObject = JSON.parseObject(response);
        if (jsonObject == null || (jsonObject.getInteger("code") != 0 && jsonObject.getInteger("code") != 10000)) {
            log.error("乐牛接口请求失败 path:{};params:{};errMsg:{}", host + path, JSONUtil.toJsonStr(params), response);
        }
        return jsonObject;
    }


    /**
     * 构建请求体
     */
    private static Map<String, Object> onBuildsRequestBody(Object content, String apikey) {
        Map<String, Object> params = new HashMap<>();
        params.put("nonceStr", RandomUtil.randomString(3));
        params.put("signType", "MD5");
        params.put("timestamp", String.valueOf(System.currentTimeMillis()));
        params.put("version", "1.0");
        params.put("content", content);
        params.put("sign", onGenerateSignature(new HashMap<>(params), apikey));
        return params;
    }

    /**
     * 加签
     */
    private static String onGenerateSignature(Map<String, Object> params, String apikey) {
        params.replace("content", JSONUtil.toJsonStr(params.get("content")));
        ArrayList<String> keys = new ArrayList<>(params.keySet());
        keys.sort(null);

        StringBuilder builders = new StringBuilder();
        for (String key : keys) {
            builders.append(key).append("=").append(params.get(key)).append("&");
        }
        String source = builders.append("key").append("=").append(apikey).toString();
        return DigestUtil.md5Hex(source).toUpperCase();
    }


}
